const axios = require('axios');
const cheerio = require('cheerio');
const fs = require('fs');
const path = require('path');

// CSV 写入函数
function saveToCSV(data, filename) {
    // 创建 CSV 头部
    const headers = 'rank,title,rating,director,quote\n';

    // 创建 CSV 内容
    const csvContent = data.map((movie, index) => {
        // 处理可能包含逗号的内容，用引号包裹
        const rank = index + 1;
        const title = `"${movie.title || ''}"`;
        const rating = movie.rating || '';
        const director = `"${movie.director || ''}"`;
        const quote = `"${movie.quote || '暂无'}"`;

        return `${rank},${title},${rating},${director},${quote}`;
    }).join('\n');

    // 写入文件
    const fullPath = path.join(__dirname, filename);
    fs.writeFileSync(fullPath, headers + csvContent, 'utf-8');
    console.log(`数据已保存到: ${fullPath}`);
}

// 设置请求配置
const url = 'https://movie.douban.com/top250';
const headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
};

// 主函数
async function fetchAndParse() {
    try {
        console.log('正在请求豆瓣 Top250 页面...\n');

        // 发送请求
        const response = await axios.get(url, { headers });

        if (response.status === 200) {
            const html = response.data;
            console.log('请求成功！开始解析...\n');

            // 方法一：使用类似 XPath 的选择器（Cheerio）
            console.log('='.repeat(60));
            console.log('方法一：使用类似 XPath 的选择器（Cheerio）');
            console.log('='.repeat(60));
            parseWithXPathLike(html);

            // 方法二：使用 CSS 选择器（Cheerio）
            console.log('\n' + '='.repeat(60));
            console.log('方法二：使用 CSS 选择器（Cheerio）');
            console.log('='.repeat(60));
            parseWithCSS(html);

            // 方法三：使用正则表达式
            console.log('\n' + '='.repeat(60));
            console.log('方法三：使用正则表达式');
            console.log('='.repeat(60));
            parseWithRegex(html);

        } else {
            console.log(`请求失败，状态码: ${response.status}`);
        }
    } catch (error) {
        console.error('发生错误:', error.message);
    }
}

// 方法一：类似 XPath 的选择器解析（使用 Cheerio 的高级选择器）
function parseWithXPathLike(html) {
    const $ = cheerio.load(html);
    const movies = [];

    // 使用属性选择器模拟 XPath: //div[@class='hd']/a/span[@class='title']
    const movieTitles = $('div[class="hd"] a span[class="title"]:first-child').map((i, el) => $(el).text()).get();

    // 模拟 XPath: //span[@class='rating_num']
    const movieRatings = $('span[class="rating_num"]').map((i, el) => $(el).text()).get();

    // 获取导演信息（从包含导演信息的 p 标签中提取）
    const directors = [];
    $('div.bd p:first-child').each((i, el) => {
        const text = $(el).text();
        const directorMatch = text.match(/导演:\s*([^\s]+)/);
        directors.push(directorMatch ? directorMatch[1] : '未知');
    });

    // 获取电影简评
    const quotes = $('span[class="inq"]').map((i, el) => $(el).text()).get();

    // 组合数据
    for (let i = 0; i < movieTitles.length; i++) {
        movies.push({
            title: movieTitles[i],
            rating: movieRatings[i] || '',
            director: directors[i] || '',
            quote: quotes[i] || '暂无'
        });

        // 打印前5部电影
        if (i < 5) {
            console.log(`\n电影: ${movieTitles[i]}`);
            console.log(`评分: ${movieRatings[i]}`);
            console.log(`导演: ${directors[i] || '未知'}`);
            console.log(`简评: ${quotes[i] || '暂无'}`);
        }
    }

    console.log(`\n共解析出 ${movies.length} 部电影`);

    // 保存到 CSV
    saveToCSV(movies, 'douban_xpath_method.csv');
}

// 方法二：CSS 选择器解析
function parseWithCSS(html) {
    const $ = cheerio.load(html);
    const movies = [];

    // 使用 CSS 选择器提取所有电影的标题
    // 相当于 Python 的: #content div.article ol li div.info div.hd a span.title
    const movieElements = $('#content div.article ol li');

    movieElements.each((index, element) => {
        const $movie = $(element);

        // 提取标题（只取第一个中文标题）
        const title = $movie.find('div.info div.hd a span.title').first().text();

        // 提取评分
        const rating = $movie.find('span.rating_num').text();

        // 提取导演
        const info = $movie.find('div.bd p').first().text();
        const directorMatch = info.match(/导演:\s*([^\s]+)/);
        const director = directorMatch ? directorMatch[1] : '未知';

        // 提取简评
        const quote = $movie.find('span.inq').text();

        movies.push({
            title,
            rating,
            director,
            quote: quote || '暂无'
        });

        // 打印前5部电影
        if (index < 5) {
            console.log(`\n电影名称: ${title}`);
            console.log(`评分: ${rating}`);
            console.log(`导演: ${director}`);
            console.log(`简评: ${quote || '暂无'}`);
        }
    });

    console.log(`\n共解析出 ${movies.length} 部电影`);

    // 保存到 CSV
    saveToCSV(movies, 'douban_css_method.csv');
}

// 方法三：正则表达式解析
function parseWithRegex(html) {
    const movies = [];

    // 正则表达式匹配电影标题
    const titlePattern = /<span class="title">([^<]+)<\/span>/g;
    const titles = [];
    let titleMatch;
    while ((titleMatch = titlePattern.exec(html)) !== null) {
        // 过滤掉英文标题（通常包含 / 开头）
        if (!titleMatch[1].startsWith(' / ')) {
            titles.push(titleMatch[1]);
        }
    }

    // 正则表达式匹配电影评分
    const ratingPattern = /<span class="rating_num" property="v:average">([\d.]+)<\/span>/g;
    const ratings = [];
    let ratingMatch;
    while ((ratingMatch = ratingPattern.exec(html)) !== null) {
        ratings.push(ratingMatch[1]);
    }

    // 正则表达式匹配导演信息
    const directorPattern = /导演:\s*([^&\s]+)/g;
    const directors = [];
    let directorMatch;
    while ((directorMatch = directorPattern.exec(html)) !== null) {
        directors.push(directorMatch[1]);
    }

    // 正则表达式匹配电影的简短描述
    const quotePattern = /<span class="inq">([^<]+)<\/span>/g;
    const quotes = [];
    let quoteMatch;
    while ((quoteMatch = quotePattern.exec(html)) !== null) {
        quotes.push(quoteMatch[1]);
    }

    // 确定最小长度
    const minLength = Math.min(titles.length, ratings.length, directors.length);

    // 组合数据
    for (let i = 0; i < minLength; i++) {
        movies.push({
            title: titles[i],
            rating: ratings[i],
            director: directors[i],
            quote: quotes[i] || '暂无'
        });

        // 打印前5部电影
        if (i < 5) {
            console.log(`\n电影: ${titles[i]}`);
            console.log(`评分: ${ratings[i]}`);
            console.log(`导演: ${directors[i]}`);
            console.log(`简评: ${quotes[i] || '暂无'}`);
            console.log('-'.repeat(40));
        }
    }

    console.log(`\n共解析出 ${movies.length} 部电影`);

    // 保存到 CSV
    saveToCSV(movies, 'douban_regex_method.csv');
}

// 执行主函数
fetchAndParse();